﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.CullingGroup
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using UnityEngine.Bindings;
using UnityEngine.Scripting;

#nullable disable
namespace UnityEngine
{
  /// <summary>
  ///   <para>Describes a set of bounding spheres that should have their visibility and distances maintained.</para>
  /// </summary>
  [NativeHeader("Runtime/Export/Camera/CullingGroup.bindings.h")]
  [StructLayout(LayoutKind.Sequential)]
  public class CullingGroup : IDisposable
  {
    internal IntPtr m_Ptr;
    private CullingGroup.StateChanged m_OnStateChanged = (CullingGroup.StateChanged) null;

    /// <summary>
    ///   <para>Create a CullingGroup.</para>
    /// </summary>
    public CullingGroup() => this.m_Ptr = CullingGroup.Init((object) this);

    ~CullingGroup()
    {
      if (!(this.m_Ptr != IntPtr.Zero))
        return;
      this.FinalizerFailure();
    }

    [FreeFunction("CullingGroup_Bindings::Dispose", HasExplicitThis = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void DisposeInternal();

    /// <summary>
    ///   <para>Clean up all memory used by the CullingGroup immediately.</para>
    /// </summary>
    public void Dispose()
    {
      this.DisposeInternal();
      this.m_Ptr = IntPtr.Zero;
    }

    /// <summary>
    ///   <para>Sets the callback that will be called when a sphere's visibility and/or distance state has changed.</para>
    /// </summary>
    public CullingGroup.StateChanged onStateChanged
    {
      get => this.m_OnStateChanged;
      set => this.m_OnStateChanged = value;
    }

    /// <summary>
    ///   <para>Pauses culling group execution.</para>
    /// </summary>
    public extern bool enabled { [MethodImpl(MethodImplOptions.InternalCall)] get; [MethodImpl(MethodImplOptions.InternalCall)] set; }

    /// <summary>
    ///   <para>Locks the CullingGroup to a specific camera.</para>
    /// </summary>
    public extern Camera targetCamera { [MethodImpl(MethodImplOptions.InternalCall)] get; [MethodImpl(MethodImplOptions.InternalCall)] set; }

    /// <summary>
    ///   <para>Sets the array of bounding sphere definitions that the CullingGroup should compute culling for.</para>
    /// </summary>
    /// <param name="array">The BoundingSpheres to cull.</param>
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void SetBoundingSpheres([Unmarshalled] BoundingSphere[] array);

    /// <summary>
    ///   <para>Sets the number of bounding spheres in the bounding spheres array that are actually being used.</para>
    /// </summary>
    /// <param name="count">The number of bounding spheres being used.</param>
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void SetBoundingSphereCount(int count);

    /// <summary>
    ///   <para>Erase a given bounding sphere by moving the final sphere on top of it.</para>
    /// </summary>
    /// <param name="index">The index of the entry to erase.</param>
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void EraseSwapBack(int index);

    public static void EraseSwapBack<T>(int index, T[] myArray, ref int size)
    {
      --size;
      myArray[index] = myArray[size];
    }

    /// <summary>
    ///   <para>Retrieve the indices of spheres that have particular visibility and/or distance states.</para>
    /// </summary>
    /// <param name="visible">True if only visible spheres should be retrieved; false if only invisible spheres should be retrieved.</param>
    /// <param name="distanceIndex">The distance band that retrieved spheres must be in.</param>
    /// <param name="result">An array that will be filled with the retrieved sphere indices.</param>
    /// <param name="firstIndex">The index of the sphere to begin searching at.</param>
    /// <returns>
    ///   <para>The number of sphere indices found and written into the result array.</para>
    /// </returns>
    public int QueryIndices(bool visible, int[] result, int firstIndex)
    {
      return this.QueryIndices(visible, -1, CullingQueryOptions.IgnoreDistance, result, firstIndex);
    }

    /// <summary>
    ///   <para>Retrieve the indices of spheres that have particular visibility and/or distance states.</para>
    /// </summary>
    /// <param name="visible">True if only visible spheres should be retrieved; false if only invisible spheres should be retrieved.</param>
    /// <param name="distanceIndex">The distance band that retrieved spheres must be in.</param>
    /// <param name="result">An array that will be filled with the retrieved sphere indices.</param>
    /// <param name="firstIndex">The index of the sphere to begin searching at.</param>
    /// <returns>
    ///   <para>The number of sphere indices found and written into the result array.</para>
    /// </returns>
    public int QueryIndices(int distanceIndex, int[] result, int firstIndex)
    {
      return this.QueryIndices(false, distanceIndex, CullingQueryOptions.IgnoreVisibility, result, firstIndex);
    }

    /// <summary>
    ///   <para>Retrieve the indices of spheres that have particular visibility and/or distance states.</para>
    /// </summary>
    /// <param name="visible">True if only visible spheres should be retrieved; false if only invisible spheres should be retrieved.</param>
    /// <param name="distanceIndex">The distance band that retrieved spheres must be in.</param>
    /// <param name="result">An array that will be filled with the retrieved sphere indices.</param>
    /// <param name="firstIndex">The index of the sphere to begin searching at.</param>
    /// <returns>
    ///   <para>The number of sphere indices found and written into the result array.</para>
    /// </returns>
    public int QueryIndices(bool visible, int distanceIndex, int[] result, int firstIndex)
    {
      return this.QueryIndices(visible, distanceIndex, CullingQueryOptions.Normal, result, firstIndex);
    }

    [FreeFunction("CullingGroup_Bindings::QueryIndices", HasExplicitThis = true)]
    [NativeThrows]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern int QueryIndices(
      bool visible,
      int distanceIndex,
      CullingQueryOptions options,
      [Unmarshalled] int[] result,
      int firstIndex);

    /// <summary>
    ///   <para>Returns true if the bounding sphere at index is currently visible from any of the contributing cameras.</para>
    /// </summary>
    /// <param name="index">The index of the bounding sphere.</param>
    /// <returns>
    ///   <para>True if the sphere is visible; false if it is invisible.</para>
    /// </returns>
    [FreeFunction("CullingGroup_Bindings::IsVisible", HasExplicitThis = true)]
    [NativeThrows]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern bool IsVisible(int index);

    /// <summary>
    ///   <para>Get the current distance band index of a given sphere.</para>
    /// </summary>
    /// <param name="index">The index of the sphere.</param>
    /// <returns>
    ///   <para>The sphere's current distance band index.</para>
    /// </returns>
    [NativeThrows]
    [FreeFunction("CullingGroup_Bindings::GetDistance", HasExplicitThis = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern int GetDistance(int index);

    /// <summary>
    ///   <para>Set bounding distances for 'distance bands' the group should compute, as well as options for how spheres falling into each distance band should be treated.</para>
    /// </summary>
    /// <param name="distances">An array of bounding distances. The distances should be sorted in increasing order.</param>
    [FreeFunction("CullingGroup_Bindings::SetBoundingDistances", HasExplicitThis = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void SetBoundingDistances([Unmarshalled] float[] distances);

    [FreeFunction("CullingGroup_Bindings::SetDistanceReferencePoint", HasExplicitThis = true)]
    private void SetDistanceReferencePoint_InternalVector3(Vector3 point)
    {
      this.SetDistanceReferencePoint_InternalVector3_Injected(ref point);
    }

    [NativeMethod("SetDistanceReferenceTransform")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void SetDistanceReferencePoint_InternalTransform(Transform transform);

    /// <summary>
    ///   <para>Set the reference point from which distance bands are measured.</para>
    /// </summary>
    /// <param name="point">A fixed point to measure the distance from.</param>
    /// <param name="transform">A transform to measure the distance from. The transform's position will be automatically tracked.</param>
    public void SetDistanceReferencePoint(Vector3 point)
    {
      this.SetDistanceReferencePoint_InternalVector3(point);
    }

    /// <summary>
    ///   <para>Set the reference point from which distance bands are measured.</para>
    /// </summary>
    /// <param name="point">A fixed point to measure the distance from.</param>
    /// <param name="transform">A transform to measure the distance from. The transform's position will be automatically tracked.</param>
    public void SetDistanceReferencePoint(Transform transform)
    {
      this.SetDistanceReferencePoint_InternalTransform(transform);
    }

    [RequiredByNativeCode]
    [SecuritySafeCritical]
    private static unsafe void SendEvents(CullingGroup cullingGroup, IntPtr eventsPtr, int count)
    {
      CullingGroupEvent* pointer = (CullingGroupEvent*) eventsPtr.ToPointer();
      if (cullingGroup.m_OnStateChanged == null)
        return;
      for (int index = 0; index < count; ++index)
        cullingGroup.m_OnStateChanged(pointer[index]);
    }

    [FreeFunction("CullingGroup_Bindings::Init")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern IntPtr Init(object scripting);

    [FreeFunction("CullingGroup_Bindings::FinalizerFailure", HasExplicitThis = true, IsThreadSafe = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void FinalizerFailure();

    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void SetDistanceReferencePoint_InternalVector3_Injected(ref Vector3 point);

    /// <summary>
    ///   <para>This delegate is used for recieving a callback when a sphere's distance or visibility state has changed.</para>
    /// </summary>
    /// <param name="sphere">A CullingGroupEvent that provides information about the sphere that has changed.</param>
    public delegate void StateChanged(CullingGroupEvent sphere);
  }
}
